#include "messageexhibition.h"
#include "mainwidget.h"
#include "selfinfoarea.h"
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QScrollBar>
#include <QPainter>
#include <QPainterPath>
#include <QMouseEvent>
#include <QFileDialog>

#define TEST_UI 1
// 消息展示区
MessageExhibition::MessageExhibition()
{
    // 1. 初始化基本属性
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    this->setWidgetResizable(true);
    // 设置滚动条的样式
    this->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 2px; background-color: rgb(240, 240, 240); }");
    this->horizontalScrollBar()->setStyleSheet("QScrollBar:horizontal { height: 0;}");
    this->setStyleSheet("QScrollArea { border: none; }");

    // 2. 创建Container容器
    container = new QWidget();
    this->setWidget(container);

    // 3. 给 container添加容器
    QVBoxLayout* vlayout = new QVBoxLayout();
    vlayout->setSpacing(0);
    vlayout->setContentsMargins(0, 0, 0, 0);
    container->setLayout(vlayout);

    // 添加测试数据
#if TEST_UI
    UserInfo userinfo;
    userinfo.userId = QString::number(114514);
    userinfo.nickname = "李田所";
    userinfo.description = "一个路过的假面演员";
    userinfo.phone = "1919810";
    userinfo.avatar = QIcon(":/res/image/default_avatar.png");

    Message message = Message::makeMessage(TEXT_TYPE, "", userinfo, QString("24岁，是学生").toUtf8(), "");
    this->addMessage(false, message);
#else
    for(int i = 1; i <= 30; i++)
    {
        UserInfo userinfo;
        userinfo.userId = QString::number(114514);
        userinfo.nickname = "李田所" + QString::number(i);
        userinfo.description = "描述：" + QString::number(i);
        userinfo.phone = "1919810";
        userinfo.avatar = QIcon(":/res/image/default_avatar.png");
        Message message = Message::makeMessage(TEXT_TYPE, "", userinfo, QString("24岁，是学生").toUtf8(), "");
        this->addMessage(false, message);
    }
#endif
}

void MessageExhibition::addMessage(bool isLeft, const Message &message)
{
    MessageItem* messageItem = MessageItem::makeMessageItem(isLeft, message);
    container->layout()->addWidget(messageItem);
}

MessageItem::MessageItem(bool isLeft)
{

}

MessageItem *MessageItem::makeMessageItem(bool isLeft, const Message &message)
{
    // 1. 创建对象 与 布局管理器
    MessageItem* messageItem = new MessageItem(isLeft);
    QGridLayout* layout = new QGridLayout();
    layout->setContentsMargins(30, 10, 40, 0);
    layout->setSpacing(10);
    messageItem->setMinimumHeight(100);
    messageItem->setLayout(layout);

    // 创建用户头像
    QPushButton* avatarBtn = new QPushButton();
    avatarBtn->setFixedSize(40, 40);
    avatarBtn->setIconSize(QSize(40, 40));
    avatarBtn->setIcon(message.sender.avatar);
    avatarBtn->setStyleSheet("QPushButton { border: none;}");

    if (isLeft) { // 根据是哪一方发送的，消息体位置也不同
        layout->addWidget(avatarBtn, 0, 0, 2, 1, Qt::AlignTop | Qt::AlignLeft);
    } else {
        layout->addWidget(avatarBtn, 0, 1, 2, 1, Qt::AlignTop | Qt::AlignLeft);
    }

    // 创建用户名 + 时间
    QLabel* nameLabel = new QLabel();
    nameLabel->setText(message.sender.nickname + " | " + message.time);
    nameLabel->setAlignment(Qt::AlignBottom);
    nameLabel->setStyleSheet("QLabel { font-size: 12px; color: rgb(178, 178, 178); }");
    if (isLeft) {
        layout->addWidget(nameLabel, 0, 1);
    } else {
        layout->addWidget(nameLabel, 0, 0, Qt::AlignRight);
    }

    // 创建消息体
    QWidget* contentWidget = nullptr;
    switch(message.messageType)
    {
    case TEXT_TYPE:
        contentWidget = makeTextMessageItem(isLeft, message.content);
        break;
    case IMAGE_TYPE:
        contentWidget = makeImageMessage(isLeft, message.fileId, message.content);
        break;
    case FILE_TYPE:
        contentWidget = makeFileMessageItem(isLeft, message);
        break;
    case SPECCH_TYPE:
        contentWidget = makeSpeechMessageItem(isLeft, message);
        break;
    default:
        LOG_ERROR() << "错误的消息类型";
    }
    if(isLeft) {
        layout->addWidget(contentWidget, 1, 1);
    } else {
        layout->addWidget(contentWidget, 1, 0);
    }

    // 连接信号槽: 点击聊天界面中的用户头像显示相关信息
    // connect(avatarBtn, &QPushButton::clicked, messageItem, (=)[]{
    //     MainWidget* mainWidget = MainWidget::getInstance();
    //     UserInfoWidget* userInfoWidget = new UserInfoWidget(message.sender, mainWidget);
    //     userInfoWidget->exec();
    // });

    // 同步修改
    // TODO...

    return messageItem;
}

QWidget *MessageItem::makeTextMessageItem(bool isLeft, const QString &text)
{
    MessageContentLabel* msgCtLabel = new MessageContentLabel(text, isLeft, TEXT_TYPE, "", QByteArray());
    return msgCtLabel;
}

QWidget *MessageItem::makeImageMessage(bool isLeft, const QString &fileId, const QByteArray &content)
{
    MessageImageLabel* messageImageLabel = new MessageImageLabel(fileId, content, isLeft);
    return messageImageLabel;
}

QWidget *MessageItem::makeFileMessageItem(bool isLeft, const Message &message)
{
    MessageContentLabel* messageContentLabel = new MessageContentLabel("[文件] " + message.fileName, isLeft, message.messageType,
                                                                       message.fileId, message.content);
    return messageContentLabel;
}

QWidget *MessageItem::makeSpeechMessageItem(bool isLeft, const Message &message)
{
    MessageContentLabel* messageContentLabel = new MessageContentLabel("[语音]", isLeft, message.messageType,
                                                                       message.fileId, message.content);
    return messageContentLabel;
}

// 文本消息正文部分
MessageContentLabel::MessageContentLabel(const QString &text, bool isLeft, const MessageType &messageType, const QString &fileId, const QByteArray &content)
    :isLeft(isLeft)
{
    // 设置基本属性
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    QFont font;
    font.setFamily("微软雅黑");
    font.setPixelSize(16);

    this->label = new QLabel(this);
    this->label->setText(text);
    this->label->setFont(font);
    this->label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
    this->label->setWordWrap(true);    // 文本自动换行
    this->label->setStyleSheet("QLabel { padding: 0 10px; line-height: 1.2; background-color: transparent; }");

    if(messageType == model::TEXT_TYPE) {
        return;
    }

    // TODO... 网络部分
}

// 显示控件时，自动调用
void MessageContentLabel::paintEvent(QPaintEvent *event)
{
    (void) event;
    //
    QObject* object = this->parent();
    if(!object->isWidgetType()) { // 确保父类是QWidget
        return;
    }

    QWidget* parent = new QWidget();
    int width = parent->width() * 0.6;

    // 2. 计算当前文本一行放置需要的宽度
    QFontMetrics metrics(this->label->font());
    int totalWidth = metrics.horizontalAdvance(this->label->text());

    // 3. 计算此处行数
    int rows = (totalWidth / (width - 40)) + 1;
    if(rows == 1) {
        width = totalWidth + 40;
    }

    int height = rows * (this->label->font().pixelSize() * 1.2 ) + 20;

    // 5. 绘制圆角矩形和箭头（聊天框）
    QPainter painter(this);
    QPainterPath path;
    // 设置 "抗锯齿"
    painter.setRenderHint(QPainter::Antialiasing);
    if (isLeft) {
        painter.setPen(QPen(QColor(255, 255, 255)));
        painter.setBrush(QColor(255, 255, 255));

        // 绘制圆角矩形
        painter.drawRoundedRect(10, 0, width, height, 10, 10);
        // 绘制箭头
        path.moveTo(10, 15);
        path.lineTo(0, 20);
        path.lineTo(10, 25);
        path.closeSubpath();   // 绘制的线形成闭合的多边形, 才能进行使用 Brush 填充颜色.
        painter.drawPath(path);  // 不要忘记真正的绘制操作

        this->label->setGeometry(10, 0, width, height);
    } else {
        painter.setPen(QPen(QColor(137, 217, 97)));
        painter.setBrush(QColor(137, 217, 97));

        // 圆角矩形左侧边的横坐标位置
        int leftPos = this->width() - width - 10; // 10 是用来容纳 箭头 的宽度
        // 圆角矩形右侧边的横坐标位置
        int rightPos = this->width() - 10;
        // 绘制圆角矩形
        painter.drawRoundedRect(leftPos, 0, width, height, 10, 10);
        // 绘制箭头
        path.moveTo(rightPos, 15);
        path.lineTo(rightPos + 10, 20);
        path.lineTo(rightPos, 25);
        path.closeSubpath();
        painter.drawPath(path);

        this->label->setGeometry(leftPos, 0, width, height);
    }

    // 6. 重新设置父元素的高度, 确保父元素足够高, 能够容纳下上述绘制的消息显示的区域
    //    注意高度要涵盖之前名字和时间的 label 的高度, 以及留点冗余空间.
    parent->setFixedHeight(height + 50);
}

void MessageContentLabel::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        // 按下左键
        if(this->messageType == FILE_TYPE) {
            if(!this->loadContentOver) {
                // TODO 数据尚未加载
                return;
            }
            // 保存文件
            saveAsFile(this->content);
        } else if (this->messageType == SPECCH_TYPE) {
            if(!this->loadContentOver) {
                // TODO 数据尚未加载
                return;
            }
            // TODO 播放语音...
        } else {
            // 其他消息不做处理
        }
    }
}

void MessageContentLabel::saveAsFile(const QByteArray &content)
{
    QString filePath = QFileDialog::getSaveFileName(this, "另存为", QDir::homePath(), "*");
    if(filePath.isEmpty()) {
        LOG_INFO() << "取消了文件存储";
        return;
    }
    Func::writeByteArrayToFile(filePath, content);
}

// 播放语音
void MessageContentLabel::playDone()
{
    if(this->label->text() == "播放中...") {
        this->label->setText("[语音]");
    }
}

// 模态对话框: 菜单项
void MessageContentLabel::contextMenuEvent(QContextMenuEvent *event)
{
    (void) event;
    if(messageType != SPECCH_TYPE)
    {
        LOG_INFO() << "目前右键菜单只支持语音消息";
        return ;
    }
}


// 用于显示图片信息
MessageImageLabel::MessageImageLabel(const QString &fileId, const QByteArray &content, bool isLeft)
    :fileId(fileId), content(content), isLeft(isLeft)
{
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    imageBtn = new QPushButton(this);
    imageBtn->setStyleSheet("QPushButton { border: none; }");


    if(content.isEmpty())
    {
        // 服务器处理...
    }
}

void MessageImageLabel::updateUI(const QString &fileId, const QByteArray &content)
{
    if(this->fileId != fileId) {
        // 当前响应的图片 是其他的图片请求
        return ;
    }

    this->content = content;
    // 绘制内容到界面
    this->update();
}

// 绘制图片到界面
void MessageImageLabel::paintEvent(QPaintEvent *event)
{
    (void) event;

    // 获取父元素
    QObject* object = this->parent();
    if(!object->isWidgetType()) {
        return ; // 虽然不可能进入该语句，从安全角度，编写
    }

    QWidget* parent = dynamic_cast<QWidget*>(object);
    int width = parent->width() * 0.6;

    // 加载 二进制数据（图片对象）
    QImage image;
    if(content.isEmpty()) {
        // 图片响应数据暂时未收到
        QByteArray tmpContent = Func::readFileToByteArray("://res/image/default_image.svg");
        image.loadFromData(tmpContent);
    } else {
        image.loadFromData(content);
    }

    // 缩放图片
    int height = 0;
    if (image.width() > width) {
        //  使用 width 作为实际的宽度
        height = ((double)image.height() / image.width()) * width;
    } else {
        // 本身宽度符合要求 不需要缩放.
        width = image.width();
        height = image.height();
    }

    // 通过pixmap作为中转，将QImage->QIcon
    QPixmap pixmap = QPixmap::fromImage(image);
    imageBtn->setIconSize(QSize(width, height));
    imageBtn->setIcon(QIcon(pixmap));

    // 确定消息体的位置
    if(isLeft) {
        imageBtn->setGeometry(10, 0, width, height);
    } else {
        int leftPos = this->width() - width * 10;
        imageBtn->setGeometry(leftPos, 0, width, height);
    }
}
